﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using devtm.Configuration;
using System.Configuration;
using System.Reflection;
using devtm.Collections;
using devtm.Helpers;
using System.Xml.Linq;
using System.Windows;
using System.Globalization;
using devtm.Editor.Configuration.Data;
using System.Collections;
using System.ComponentModel;
using devtm.Configuration.Models;
using devtm.Editor.Configuration.Templates;
using devtm.Config;


namespace devtm.Editor.Configuration
{
    public class ConfigPropertiesCollection : TableCollection<IConfigProperty, String>
    {

        public String SectionName { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="ConfigPropertiesCollection"/> class.
        /// </summary>
        /// <param name="section">The section.</param>
        public ConfigPropertiesCollection(ElementSection section)
            : base(c => c.PropertyName)
        {

            this.Section = section;

            if (Section.ConfigurationElement == null)
            {
                this.Add(new TemplateDefault());
                return;
            }

            ButtonAction();
            GetProperties();

        }


        #region Add Item Collection

        private object AddItemToSection(ElementSection elementSection)
        {
            throw new NotImplementedException();
        }

        #endregion 


        #region button

        private void ButtonAction()
        {

            if (this.Section.ButtonActions.Count > 0)
            {
                foreach (ElementAction act in this.Section.ButtonActions)
                {
                    if (act.IsForChildren || act.TypeAction != EnumAction.Undefine)
                        continue;

                    this.Add(new TemplateMethod
                        (act.Action
                        , this.Section
                        , act.Label

                        ));

                }
            }
        }

        #endregion

        #region FindEditeur

        private void GetProperties()
        {

            foreach (PropertyInfo propertyInfo in Section.ConfigurationElement.GetType().GetProperties())
                try
                {

                    if ("|Count|AllKeys|EmitClear|IsSynchronized|SyncRoot|SectionInformation|LockAttributes|LockItem|ElementInformation|LockAllElementsExcept|LockElements|LockAllAttributesExcept|CurrentConfiguration".Contains("|" + propertyInfo.Name))
                        return;

                    Type t = propertyInfo.PropertyType;

                    if (t.IsOfType(typeof(ConfigurationElement)))
                        continue;

                    IConfigProperty ret = FindEditeur(t, propertyInfo, Section);

                    ret.MyPropertyChanged("Value");

                }
                catch (Exception ex)
                {
                    MessageBox.Show(String.Format(System.Globalization.CultureInfo.CurrentCulture
                        , Properties.Resources.TheElementSectionCanTBeShowedALibraryIsProbablyMissing
                        , propertyInfo.Name, ex.Message));
                }

        }

        private IConfigProperty FindEditeur(Type t, PropertyInfo propertyInfo, ElementSection section)
        {
            IConfigProperty ret;
            CustomDesignerAttribute Att = propertyInfo.GetDesignAttribute(section);
            if (Att != null)
            {
                if (CustomEditeur(Att, propertyInfo, section, out ret))
                    return ret;
            }

            else
                if (DefaultEditeur(t, propertyInfo, section, out ret))
                    return ret;

            this.Add(new TemplateDefault(propertyInfo, section));

            return ret;

        }


        private bool CustomEditeur(CustomDesignerAttribute att, PropertyInfo propertyInfo, ElementSection instance, out IConfigProperty ret)
        {

            ret = null;

            if (att.TypeDesigner == ConfigConstants.Design.IgnoreParam)
                return true;

            switch (att.TypeDesigner)
            {
                case ConfigConstants.Design.IgnoreParam:
                    return true;
                case ConfigConstants.Design.ConnexionStringNameParam:
                    ret = this.Add(new TemplateConnexionStringName(propertyInfo, instance));
                    break;
                case ConfigConstants.Design.IPHostDesignerParam:
                    ret = this.Add(new TemplateHost(propertyInfo, instance));
                    break;
                case ConfigConstants.Design.TypeDesignerParam:
                    ret = this.Add(new TemplateType(propertyInfo, instance));
                    break;
                case ConfigConstants.Design.RequireConfigurationSectionParam:
                    break;
                case ConfigConstants.Design.ListOfDesignerParam:
                    break;
                case ConfigConstants.Design.StringParam:
                    ret = this.Add(new TemplateString(propertyInfo, instance));
                    break;
                case ConfigConstants.Design.DateTimeParam:
                    ret = this.Add(new TemplateDateTime(propertyInfo, instance));
                    break;
                case ConfigConstants.Design.BoolParam:
                    break;
                case ConfigConstants.Design.IntegerParam:
                    break;
                case ConfigConstants.Design.TimeSpanParam:
                    ret = this.Add(new TemplateTimeSpan(propertyInfo, instance));
                    break;
                case ConfigConstants.Design.UriParam:
                    this.Add(new TemplateUri(propertyInfo, instance));
                    break;
                case ConfigConstants.Design.VersionParam:
                    this.Add(new TemplateVersion(propertyInfo, instance));
                    break;
                case ConfigConstants.Design.ListeSelectorParam:
                    ret = this.Add(new TemplateListeSelector(propertyInfo, instance, (ListeSelectorAttribute)att));
                    break;
                default:
                    return false;
            }
               
            return true;
        }

        private bool DefaultEditeur(Type t, PropertyInfo propertyInfo, ElementSection instance, out IConfigProperty ret)
        {

            ret = null;

            if (t.IsClass)
            {
                if (t == typeof(String))
                {
                    var o = BoxSetting.GetBoxSetting(propertyInfo, ConfigConstants.Design.Key).FirstOrDefault();
                    if (o != null)
                    {

                        ret = new TemplateString(propertyInfo, instance);

                        switch (o.ValueString)
                        {
                            case ConfigConstants.Design.ConnexionStringNameParam:
                                ret = new TemplateConnexionStringName(propertyInfo, instance);
                                break;

                            case ConfigConstants.Design.IPHostDesignerParam:
                                ret = new TemplateHost(propertyInfo, instance);
                                break;
                                
                        }
                    }
                    else
                        ret = new TemplateString(propertyInfo, instance);
                }
                else if (t == typeof(Type))
                    ret = new TemplateType(propertyInfo, instance);
                
                else if (t == typeof(Uri))
                    ret = new TemplateUri(propertyInfo, instance);

                else if (t == typeof(Version))
                    ret = new TemplateVersion(propertyInfo, instance);

                else if (t == typeof(System.Collections.Specialized.NameValueCollection))
                    ret = new TemplateNameValueCollection(propertyInfo, instance);

            }
            else
            {
                if (t == typeof(int) || t == typeof(Int64))
                    ret = new TemplateInteger(propertyInfo, instance);

                else if (t == typeof(bool))
                    ret = new TemplateBool(propertyInfo, instance);

                else if (t.IsEnum)
                    ret = new TemplateEnum(propertyInfo, instance);

                else if (t == typeof(TimeSpan))
                    ret = new TemplateTimeSpan(propertyInfo, instance);

                else if (t == typeof(DateTime))
                    ret = new TemplateDateTime(propertyInfo, instance);
                
            }


            if (ret == null)
                return false;

            this.Add(ret);

            return true;

        }

       ///// <summary>
       // ///  return the Designer attribute
       // /// </summary>
       // /// <param name="propertyInfo"></param>
       // /// <returns></returns>
       // private CustomDesignerAttribute GetDesignAttribute(PropertyInfo propertyInfo)
       // {
       //     Attribute[] Atts = Attribute.GetCustomAttributes(propertyInfo);
       //     foreach (Attribute item in Atts)
       //         if (item.GetType().IsOfType(typeof(CustomDesignerAttribute)))
       //             return (CustomDesignerAttribute)item;

       //     return DictionaryTemplate.GetCustomDesignerAttribute(propertyInfo, Section);

       // }

        #endregion
    
        public ElementSection Section { get; private set; }


        
    }

}
